package com.wugz.app.zookeeperconfig.config;


import com.lagou.export.RpcExportUtils;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;

/**
 * 数据库配置
 */
@Configuration
@MapperScan(basePackages = "com.wugz.app.zookeeperconfig.mapper", sqlSessionFactoryRef = "primarySqlSessionFactory")
public class DataSourceConfig implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public static final String ONE_KEY = "ONE_KEY";

    @Bean(name = "primaryDataSource")
    @Primary
    public DynamicDataSource dataSource(@Qualifier("localProperties") Properties properties) throws Exception {
        Map<String, String> param = RpcExportUtils.getDbSource(properties);
        DynamicDataSource source = new DynamicDataSource();

        HikariDataSource ds = setProperties(param);

        source.setTargetDataSources(Collections.singletonMap(ONE_KEY, ds));

        return source;
    }

    private HikariDataSource setProperties(Map<String, String> param) {
        HikariDataSource ds = new HikariDataSource();

        ds.setJdbcUrl(param.get("url"));
        ds.setUsername(param.get("username"));
        ds.setPassword(param.get("password"));

        return ds;
    }


    public void addListener() throws Exception {
        CuratorFramework client = RpcExportUtils.getClient();

        PathChildrenCache childrenCache = new PathChildrenCache(client, RpcExportUtils.JDBC_NODE, false);

        childrenCache.start(PathChildrenCache.StartMode.NORMAL);

        childrenCache.getListenable().addListener((curatorFramework, pathChildrenCacheEvent) -> {
            switch (pathChildrenCacheEvent.getType()) {
//                增删改时触发
                case CHILD_ADDED:
                case CHILD_UPDATED:
                case CHILD_REMOVED:
                    DynamicDataSource source = applicationContext.getBean(DynamicDataSource.class);

                    HikariDataSource ds = setProperties(RpcExportUtils.getDbSource(null));
                    //当检测到数据库地址改变时，重新设置数据源
                    source.setTargetDataSources(Collections.singletonMap(ONE_KEY, ds));
                    source.afterPropertiesSet();
            }
        });
    }

//    获取初始配置
    @Bean
    @Primary
    @ConfigurationProperties(prefix = "hikari.primary")
    public Properties localProperties() {
        return new Properties();
    }

    @Bean(name = "primarySqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("/mappers/*.xml"));
        SqlSessionFactory factory = sessionFactory.getObject();

        //添加数据源配置监听
        addListener();

        return factory;
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

